<?php
namespace app\apijson\query;

use app\apijson\core\ApiJsonException;

/**
 * TableQuery
 *
 * 负责处理 type=table 的 key，即单表/多表的查询、递归、字段别名等。
 * 由 QueryBuilder 调用。
 */
class TableQuery
{
    /**
     * @var QueryBuilder 主调度器，便于递归
     */
    protected $builder;
    public function __construct($builder)
    {
        $this->builder = $builder;
    }
    /**
     * 处理单表/多表查询
     * @param string $key   表名
     * @param array  $value 解析后的参数结构
     * @return array|object 查询结果
     * @throws ApiJsonException
     */
    public function handle($key, $value)
    {
        // 兼容原 queryTable 逻辑
        $model = $this->getModel($key);
        if (!$model) {
            throw new ApiJsonException("Model for table '$key' is not defined in ModelMap");
        }
        $params = $value['params'];
        $parentData = $value['parent'] ?? [];
        $query = $model::query();
        foreach ($params as $k => $v) {
            if (in_array($k, ['page', 'count', 'query'])) continue;
            OperatorHandler::apply($query, $k, $v, $parentData);
        }
        $hasPage = array_key_exists('page', $params);
        $hasCount = array_key_exists('count', $params);
        $page = $hasPage ? intval($params['page']) : null;
        $count = $hasCount ? intval($params['count']) : null;
        $queryFlag = $params['query'] ?? 0;
        if ($queryFlag == 1) {
            return ['total' => $query->count()];
        } elseif ($queryFlag == 2) {
            $total = $query->count();
            if ($hasPage || $hasCount) {
                $query->skip($page ? $page * ($count ?? 10) : 0);
                $query->take($count ?? 10);
            }
            $data = $query->get()->toArray();
            $aliasMap = OperatorHandler::getAliasMap($query);
            if ($aliasMap) {
                foreach ($data as &$row) {
                    foreach ($aliasMap as $field => $alias) {
                        if (array_key_exists($field, $row)) {
                            $row[$alias] = $row[$field];
                            unset($row[$field]);
                        }
                    }
                }
            }
            foreach ($params as $k => $v) {
                if (is_array($v) && isset($v['type']) && $v['type'] === 'table') {
                    foreach ($data as &$row) {
                        $row[$k] = $this->builder->build([
                            $k => [
                                'type' => 'table',
                                'params' => $v['params'],
                                'parent' => [$key => $row],
                            ]
                        ])[$k];
                    }
                }
            }
            return [
                'list' => $data,
                'total' => $total
            ];
        } else {
            if ($hasPage || $hasCount) {
                $query->skip($page ? $page * ($count ?? 10) : 0);
                $query->take($count ?? 10);
            }
            $data = $query->get()->toArray();
            $aliasMap = OperatorHandler::getAliasMap($query);
            if ($aliasMap) {
                foreach ($data as &$row) {
                    foreach ($aliasMap as $field => $alias) {
                        if (array_key_exists($field, $row)) {
                            $row[$alias] = $row[$field];
                            unset($row[$field]);
                        }
                    }
                }
            }
            foreach ($params as $k => $v) {
                if (is_array($v) && isset($v['type']) && $v['type'] === 'table') {
                    foreach ($data as &$row) {
                        $row[$k] = $this->builder->build([
                            $k => [
                                'type' => 'table',
                                'params' => $v['params'],
                                'parent' => [$key => $row],
                            ]
                        ])[$k];
                    }
                }
            }
            return $data;
        }
    }

    /**
     * 新增数据
     * @param string $key
     * @param array $value
     * @return array|object
     */
    public function insert($key, $value)
    {
        $model = $this->getModel($key);
        if (!$model) {
            throw new ApiJsonException("Model for table '$key' is not defined in ModelMap");
        }
        $params = $value['params'];
        // 过滤掉只读参数
        $data = array_filter($params, function($k) {
            return strpos($k, '@') !== 0 && !in_array($k, ['type', 'parent']);
        }, ARRAY_FILTER_USE_KEY);
        $instance = $model::create($data);
        return $instance ? $instance->toArray() : null;
    }

    /**
     * 更新数据
     * @param string $key
     * @param array $value
     * @return int 影响行数
     */
    public function update($key, $value)
    {
        $model = $this->getModel($key);
        if (!$model) {
            throw new ApiJsonException("Model for table '$key' is not defined in ModelMap");
        }
        $params = $value['params'];
        // 过滤掉只读参数
        $data = array_filter($params, function($k) {
            return strpos($k, '@') !== 0 && !in_array($k, ['type', 'parent']);
        }, ARRAY_FILTER_USE_KEY);
        // 约定：必须有主键 id
        if (!isset($params['id'])) {
            throw new ApiJsonException('更新操作必须指定主键 id');
        }
        $instance = $model::find($params['id']);
        if (!$instance) {
            throw new ApiJsonException('未找到要更新的数据 id=' . $params['id']);
        }
        $instance->fill($data);
        $instance->save();
        return $instance->toArray();
    }

    /**
     * 删除数据
     * @param string $key
     * @param array $value
     * @return array|int
     */
    public function delete($key, $value)
    {
        $model = $this->getModel($key);
        if (!$model) {
            throw new ApiJsonException("Model for table '$key' is not defined in ModelMap");
        }
        $params = $value['params'];
        // 约定：必须有主键 id
        if (!isset($params['id'])) {
            throw new ApiJsonException('删除操作必须指定主键 id');
        }
        $instance = $model::find($params['id']);
        if (!$instance) {
            throw new ApiJsonException('未找到要删除的数据 id=' . $params['id']);
        }
        $instance->delete();
        return ['deleted' => true, 'id' => $params['id']];
    }
    /**
     * 获取模型类
     * @param string $table 表名
     * @return string|null  模型类名
     */
    protected function getModel($table)
    {
        $map = include __DIR__ . '/../config/ModelMap.php';
        $key = strtolower($table);
        return $map[$key] ?? null;
    }
} 